import pgzrun
import time
import random
WIDTH=1120 #必须为imgs*2的倍数
HEIGHT=800 #必须为imgs*2的倍数
snake=[Actor("snake_head",(WIDTH//2,HEIGHT//2))] #初始化蛇列表
snake[0].angle=-90 #angle,该actor的角度（详见附录一）
imgs=80 #图片大小
speed=4.75 #速度，最大值为5
dir=[1,0] #蛇头前进方向
start=3
long=start #蛇的长度
ani=animate(snake[0],pos=snake[0].pos) #animate会返回一个Animation类的变量，在此为初始化（详见附录一）
food=Actor("food")
pop=tone.create('A3', 0.5)

BACK_COLOR=(30,30,30) #背景色

def Init_snake(long): #初始化蛇身
    global snake
    for i in range(long-1):
        snake.append(Actor("snake",(WIDTH//2-imgs*(i+1),HEIGHT//2)))

def new_food():
    global food
    food.pos=(random.randint(2,WIDTH//imgs-2)*imgs,random.randint(2,HEIGHT//imgs-2)*imgs)

def on_key_down(key): #控制方向
    global dir
    if key==keys.UP and dir[0]: #上
        dir[0]=0
        dir[1]=-1
        snake[0].angle=360 #调整蛇头角度
    if key==keys.DOWN and dir[0]: #下
        dir[0]=0
        dir[1]=1
        snake[0].angle=-180 #调整蛇头角度
    if key==keys.LEFT and dir[1]: #左
        dir[0]=-1
        dir[1]=0
        snake[0].angle=90 #调整蛇头角度
    if key==keys.RIGHT and dir[1]: #右
        dir[0]=1
        dir[1]=0
        snake[0].angle=-90 #调整蛇头角度

def again():
    global dir,snake,long,ani
    time.sleep(0.5) #暂停0.5秒动画
    long=start #将长度设为初始数字
    snake=[Actor("snake_head",(WIDTH//2,HEIGHT//2))]
    snake[0].angle=-90 #把蛇头角度调整
    Init_snake(long) #把蛇身再次初始化
    dir=[1,0] #把方向调整
    new_food()

Init_snake(long)
new_food()

def update():
    global dir,snake,long,ani
    if(ani.running==False): #Animation类的内部变量running，如果动画正在执行为True，反之为False
        for i in range(long-1,0,-1): #循环遍历蛇身
            animate(snake[i],pos=snake[i-1].pos,duration=(5-speed)) #对蛇身进行动画
        ani=animate(snake[0],pos=(snake[0].pos[0]+dir[0]*imgs,snake[0].pos[1]+dir[1]*imgs),duration=(5-speed)) #对蛇头进行动画

    if(snake[0].pos[0]>WIDTH-imgs//2 or snake[0].pos[0]<imgs//2 or snake[0].pos[1]>HEIGHT-imgs//2 or snake[0].pos[1]<imgs//2): #如果蛇撞到了屏幕边缘
        again()
    for i in range(2,long): #检测是否碰撞身体 
        if snake[i].distance_to(snake[0].pos)<imgs:
            again()
            break
    if snake[0].distance_to(food.pos)<imgs:
        pop.play()
        snake.insert(0,Actor("snake_head",food.pos))
        snake[0].angle=snake[1].angle
        ani=animate(snake[0],pos=(snake[0].pos[0]+dir[0]*imgs,snake[0].pos[1]+dir[1]*imgs),duration=(5-speed))
        snake[1].image="snake"
        long+=1
        new_food()

def draw():
    screen.clear()
    screen.fill(BACK_COLOR)
    food.draw()
    for i in snake: #绘制蛇
        i.draw()
    screen.draw.text(str(long), (20, 20),fontsize=64)

pgzrun.go()

'''
附录1：
    Animation类
    此类变量由animate函数返回，由如下内部变量：
     -running 如果此动画正在运行，为True，反之为False
     -on_finished 此动画结束时的执行函数
    还有一个内部函数：
     -stop(complete=False) 强制结束此动画，参数complete非必传，默认为False，作用为设置对应animate的target
    更多详见 https://pygame-zero.readthedocs.io/zh_CN/latest/builtins.html#id17

    angle变量
    此变量是Actor类的内部变量，用于修改角色的角度（仅仅是外形上的），注意，修改此变量会同时更改Actor的寬高
    注意：
    左 90
    上 360
    右 -90
    下 -180
    特别：0度=360度=720度=7200度=......
         x度=x+360*n度
         n为任意自然数
    更多详见 https://pygame-zero.readthedocs.io/zh_CN/latest/builtins.html#id15
'''